﻿//----------------------------------------------------------------
// Desc: 
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2012-04-13
//
// Update Date : 
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


class IFThreadObject : public IFMemObject
{
    friend unsigned int FCALL FThread_WorkThreadFunc(void* lpThreadParameter);

protected:
    explicit IFThreadObject()
        :hThread(0)
        ,nCmd(eTC_Exit)
        ,bWorking(false)
    {}

public:
    // 获取线程的打印或者现实名
    virtual const ACHAR* GetThreadName()
    {
        return this->ClassName();
    }
    // 线程是否创建成功的
    virtual bool IsInitialize()
    {
        return hThread != 0;
    }
    // 开始启动线程
    virtual bool Start()
    {
        if (hThread)
            return false;
        nCmd = eTC_Pause;
        hThread = FCreateThread(0, FGetThreadEngine(), this, 0);
        FASSERT(hThread, _T("创建线程失败"));
        nCmd = (hThread ? eTC_Run : eTC_Exit);
        return hThread != 0;
    }
    // 结束线程（由线程体外部对象调用）
    virtual void Exit()
    {
        FWaitThreadEnd(hThread, nCmd);
    }
    // 结束线程（由线程体内部对象调用）
    virtual void Stop(UINT code = 0)
    {
        nCmd = eTC_Exit;
    }
    // 暂停并挂起线程
    virtual void Suspend()
    {
        if (!hThread)
            return;

        nCmd = eTC_Pause;
        while (bWorking)
            FSleep(1);
        FSuspendThread(hThread);
    }
    // 恢复挂起的线程
    virtual void Resume()
    {
        if (!hThread)
            return;

        nCmd = eTC_Run;
        FResumeThread(hThread);
    }
    // 运行线程，所有线程对象均要继承此接口（此函数不需要阻塞，由主循环泵循环调用此接口）
    // 如需需在此线程函数内部结束线程，请调用Stop，在其它函数中则调整用Exit
    virtual void Run() = 0;

protected:
    HANDLE hThread;             // 加载线程句柄
    EF_THREAD_COMMAND nCmd;     // 当前多线程命令
    bool bWorking;              // 线程是否在执行任务中，即是否正在处理Run函数
    FLockObject csLock;         // 数据安全锁，在函数中第一句使用FLock_Auto
};
